package com.superb.gateway.route;

import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

/**
 * 动态路由
 * @Author: ajie
 * @CreateTime: 2024-04-28 15:57
 * 实现spring提供的事件推送接口
 */
@Slf4j
@Component
@SuppressWarnings("all")
public class SuperbDynamicRouteService implements ApplicationEventPublisherAware {

    @Resource
    private RouteDefinitionWriter routeDefinitionWriter;

    private ApplicationEventPublisher publisher;

    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        // 完成spring事件推送的句柄初始化
        this.publisher = applicationEventPublisher;
    }

    /**
     * 添加路由
     * @param definition
     * @return
     */
    public String insert(RouteDefinition definition) {
        // gateway路由订阅
        this.routeDefinitionWriter.save(Mono.just(definition)).subscribe();
        // 推送路由
        this.publisher.publishEvent(new RefreshRoutesEvent(this));
        return "success";
    }

    /**
     * 删除路由
     * @param definition
     * @return
     */
    public String delete(RouteDefinition definition) {
        try {
            // 删除gateway路由id
            this.routeDefinitionWriter.delete(Mono.just(definition.getId()));
            return "delete success";
        } catch (Exception e) {
            log.error("gateway delete route fail: {}", e.getMessage(), e);
            return "delete fail";
        }
    }

    /**
     * 更新路由
     * @param definition
     * @return
     */
    public String update(RouteDefinition definition) {
        this.delete(definition);
        this.insert(definition);
        // 推送路由
        this.publisher.publishEvent(new RefreshRoutesEvent(this));
        return "success";
    }

}
